/**
 * 
 */
package datamodel.trie;

/**
 * the whole trie<br>
 * provides communication functionality 
 * 
 * @author Jakob Karolus, Kevin Munk
 * @version 1.0
 *
 */
public class Trie {
	
	/**
	 * Represents the possible group codes for use with Tries
	 */
	public static String[] TRIE_CODES = {"0000","0001","0010","0011","0100","0101","0110","0111",
											"1000","1001","1010","1011","1100","1101","1110","1111"};
	
	/**
	 * Represents the root of this Trie
	 */
	TrieNode root = null;
	
	/**
	 * Represents the current node in this Trie
	 */
	TrieNode currentNode = null;
	
	/**
	 * Constructor
	 */
	public Trie(){
		this.root = new TrieNode();
		this.moveToRoot();
	}

	/**
	 * Determines if the given group code is valid
	 * @param group is the given group code
	 * @return true if the given group code is valid
	 */
	public static boolean isValidGroup(String group){
		if(group.length() == 4){
			for(int i = 0; i < 4; i++){
				if(group.charAt(i) != '1' && group.charAt(i) != '0')
					return false;
			}
			return true;
		}
		return false;
	}
	
	/**
	 * Retrieves the current node in this Trie
	 * @return the current node in this Trie
	 */
	public TrieNode getCurrentNode(){
		return this.currentNode;
	}
	
	/**
	 * Determines if the Trie has a root
	 * @return true if this Trie has a root
	 */
	public boolean hasRoot(){
		return (root != null);
	}
	
	/**
	 * Moves the current node to the root of this Trie
	 * @return
	 */
	public boolean moveToRoot(){
		if (this.hasRoot()){
			return this.setCurrentNode(this.root);
		}
		return false;
	}
	
	/**
	 * Determines if the Trie's current node has a child for the given group
	 * @param group is the given group
	 * @return true if the Trie's current node has a child for the given group
	 */
	public boolean hasChildForGroup(String group){
		if(this.currentNode == null){
			return false;
		}
		if(isValidGroup(group)){
			return this.currentNode.hasChild(group);
		}
		throw new IllegalArgumentException("Invalid group name");
	}
	
	/**
	 * Sets a specified TrieNode as the child of this Trie's current node corresponding to a given group
	 * @param child is the child TrieNode to be set
	 * @param group is the group to which the child belongs
	 * @return true if the setting was successful
	 */
	public boolean setChildForGroup(TrieNode child, String group) {
		if(this.currentNode == null){
			return false;
		}
		return (this.currentNode.setChildForGroup(child, group));
		
	}
	
	/**
	 * Moves the current node to the child in the specified group
	 * @param group is the specified group
	 * @return true if the move was successful
	 */
	public boolean moveToChild(String group){
		if(this.hasChildForGroup(group)){
			return this.setCurrentNode(this.currentNode.getChild(group));
		}
		return false;
	}
	
	/**
	 * Moves the current node to its parent
	 * @return true if the move was successful
	 */
	public boolean moveToParent(){
		if(this.currentNode == null){
			return false;
		}
		if(this.currentNode.hasParent()){
			return this.setCurrentNode(this.currentNode.getParent());
		}
		return false;
	}
	
	/**
	 * Sets the current node to a specified TrieNode
	 * @param node is the specified TrieNode
	 * @return true if the setting was successful
	 */
	public boolean setCurrentNode(TrieNode node){
		if(this.root == null){
			this.root = node;
			return this.moveToRoot();
		} else {
			this.currentNode = node;
			return true;
		}
	}
	
	/**
	 * CLears the tree
	 */
	public void clear(){
		this.root = null;
		this.moveToRoot();
	}

		//TODO: add attributes and methods for your implementation


}
